#include <aiui/aiui.h>
AIUI::AIUI():
    Config("resource/config/aiui.json"),
    IAgentComponent(AgentComponentType::NLP,false){
    showPanel = getValue("showPanel").asBool();
}
void AIUI::Update(){
	if(!showPanel)return;
    static char inputText[1024] = "今天天气怎么样？";
    ImGui::Begin("AIUI Controller");
    ImGui::InputTextMultiline("输入文本",inputText,sizeof(inputText),ImVec2(-1.0f, ImGui::GetTextLineHeight() * 8));
    if(ImGui::Button("提交",ImVec2(-1.0f, 0.0f))){
        WriteText(inputText);
    }
	ImGui::Text(message_sum.c_str());
    ImGui::End();
}
void AIUI::PollMessage(Message message){
	if(message.fromType == AgentComponentType::SPEECH){
		string type = message.content.at(0);
		if(type == "STTOK")WriteText(message.content.at(1));
	}
	if(message.fromType == AgentComponentType::GUI){
		string type = message.content.at(0);
		if(type == "OPEN_NLP")showPanel = true;
	}
}
void AIUI::Init(){
	mTtsFileHelper = new FileUtil::DataFileHelper("");

    AIUISetting::setAIUIDir("./resource/AIUI/");
	AIUISetting::initLogger("./resource/AIUI/log");
    Json::Value paramJson;
	Json::Value appidJson;

	appidJson["appid"] = appid;
	
	string fileParam = FileUtil::readFileAsString("./resource/AIUI/cfg/aiui.cfg");
	Json::Reader reader;
	if(reader.parse(fileParam, paramJson, false))
	{
		paramJson["login"] = appidJson;

		//for ivw support
		string wakeup_mode = paramJson["speech"]["wakeup_mode"].asString();

		//如果在aiui.cfg中设置了唤醒模式为ivw唤醒，那么需要对设置的唤醒资源路径作处理，并且设置唤醒的libmsc.so的路径为当前路径
		if(wakeup_mode == "ivw")
		{
			//readme中有说明，使用libmsc.so唤醒库，需要调用MSPLogin()先登录
			//string lgiparams = "appid=5c223f6c,engine_start=ivw";
			//MSPLogin(NULL, NULL, lgiparams.c_str());
			string ivw_res_path = paramJson["ivw"]["res_path"].asString();
			if(!ivw_res_path.empty())
			{
				ivw_res_path = "fo|" + ivw_res_path;
				paramJson["ivw"]["res_path"] = ivw_res_path;
			}

			string ivw_lib_path = "libmsc.so";

			paramJson["ivw"]["msc_lib_path"] = ivw_lib_path;
		}
		//end
		Json::FastWriter writer;
		string paramStr = writer.write(paramJson);
		aiui_agent = IAIUIAgent::createAgent(paramStr.c_str(), this);
	}
	else
	{
		cout << "aiui.cfg has something wrong!" << endl;
	}
    Wake();
}
void AIUI::Wake(){
    if (nullptr != aiui_agent)
	{
		IAIUIMessage * wakeupMsg = IAIUIMessage::create(AIUIConstant::CMD_WAKEUP);
		aiui_agent->sendMessage(wakeupMsg);
		wakeupMsg->destroy();
	}
}
void AIUI::WriteText(string text){
    if (nullptr != agent)
	{
		// textData内存会在Message在内部处理完后自动release掉
		Buffer* textData = Buffer::alloc(text.length());
		text.copy((char*) textData->data(), text.length());

		IAIUIMessage * writeMsg = IAIUIMessage::create(AIUIConstant::CMD_WRITE,
			0,0, "data_type=text", textData);	

		aiui_agent->sendMessage(writeMsg);
		writeMsg->destroy();		
	}
}
void AIUI::ParseNLP(string result) const{
	cout<<result<<endl;
	Json::Value root;
	Json::Reader reader;
	reader.parse(result,root,false);
	string service = root["intent"]["service"].asString();
	string commonRet = root["intent"]["answer"]["text"].asString();
	if(commonRet != ""){
		cout<<commonRet<<endl;
		message_sum.append(commonRet+"\n");
		agent->PushMessage(Message(AgentComponentType::NLP,vector<string>{"commonRet",commonRet}));
	}
	agent->PushMessage(Message(AgentComponentType::NLP,vector<string>{service,result}));
}
void AIUI::onEvent(const IAIUIEvent& event) const{
    switch (event.getEventType()) {
	//SDK 状态回调
	case AIUIConstant::EVENT_STATE:
		{
			switch (event.getArg1()) {
			case AIUIConstant::STATE_IDLE:
				{
					cout << "EVENT_STATE:" << "IDLE" << endl;
				} break;

			case AIUIConstant::STATE_READY:
				{
					cout << "EVENT_STATE:" << "READY" << endl;
				} break;

			case AIUIConstant::STATE_WORKING:
				{
					cout << "EVENT_STATE:" << "WORKING" << endl;
				} break;
			}
		} break;

	//唤醒事件回调
	case AIUIConstant::EVENT_WAKEUP:
		{
			cout << "EVENT_WAKEUP:" << event.getInfo() << endl;
		} break;

	//休眠事件回调
	case AIUIConstant::EVENT_SLEEP:
		{
			cout << "EVENT_SLEEP:arg1=" << event.getArg1() << endl;
		} break;

	//VAD事件回调，如找到前后端点
	case AIUIConstant::EVENT_VAD:
		{
			switch (event.getArg1()) {
			case AIUIConstant::VAD_BOS:
				{
					cout << "EVENT_VAD:" << "BOS" << endl;
				} break;

			case AIUIConstant::VAD_EOS:
				{
					cout << "EVENT_VAD:" << "EOS" << endl;
				} break;

			case AIUIConstant::VAD_VOL:
				{
					//						cout << "EVENT_VAD:" << "VOL" << endl;
				} break;
			}
		} break;

	//最重要的结果事件回调
	case AIUIConstant::EVENT_RESULT:
		{
			Json::Value bizParamJson;
			Json::Reader reader;
			
			if (!reader.parse(event.getInfo(), bizParamJson, false)) {
				cout << "parse error!" << endl << event.getInfo() << endl;
				break;
			}
			Json::Value data = (bizParamJson["data"])[0];
			Json::Value params = data["params"];
			Json::Value content = (data["content"])[0];
			string sub = params["sub"].asString();
			//sub字段表示结果的类别，如iat听写，nlp语义结果
			cout << "EVENT_RESULT:" << sub << endl;

			if (sub == "nlp")
			{
				Json::Value empty;
				Json::Value contentId = content.get("cnt_id", empty);

				if (contentId.empty())
				{
					cout << "Content Id is empty" << endl;
					break;
				}

				string cnt_id = contentId.asString();
				int dataLen = 0;
				const char* buffer = event.getData()->getBinary(cnt_id.c_str(), &dataLen);
				string resultStr;

				if (NULL != buffer)
				{
					resultStr = string(buffer, dataLen);

					//cout << resultStr << endl;
					ParseNLP(resultStr);
				}
				else
				{
					cout << "buffer is NULL" << endl;
				}
			} 
			else if (sub == "tts")
			{
				cout << event.getInfo() << endl;

				string cnt_id = content["cnt_id"].asString();

				int dataLen = 0;
				const char* data = event.getData()->getBinary(cnt_id.c_str(), &dataLen);

				cout << "data_len=" << dataLen << endl;

				int dts = content["dts"].asInt();
				cout << "dts=" << dts << endl;

				string errorinfo = content["error"].asString();

				cout << "error info is " << errorinfo << endl;

				if (2 == dts && errorinfo == "AIUI DATA NULL")
				{
					//满足这两个条件的是空结果,不处理,直接丢弃
				}
				else if (3 == dts)
				{
					cout << "tts result receive dts = 3 result" << endl;
					mTtsFileHelper->createWriteFile("tts", ".pcm", false);
					mTtsFileHelper->write((const char*) data, dataLen, 0, dataLen);
					mTtsFileHelper->closeFile();
				}
				else
				{
					if (0 == dts)
					{
						mTtsFileHelper->createWriteFile("tts", ".pcm", false);
					}

					mTtsFileHelper->write((const char*) data, dataLen, 0, dataLen);

					if (2 == dts)
					{
						mTtsFileHelper->closeWriteFile();
					}
				}
			}

		}
		break;

		//上传资源数据的返回结果
	case AIUIConstant::EVENT_CMD_RETURN:
	{
		//cout << "onEvent --> EVENT_CMD_RETURN: arg1 is " << event.getArg1() << endl;
		if (AIUIConstant::CMD_SYNC == event.getArg1())
		{
			int retcode = event.getArg2();
			int dtype = event.getData()->getInt("sync_dtype", -1);

			//cout << "onEvent --> EVENT_CMD_RETURN: dtype is " << dtype << endl;

			switch (dtype)
			{
				case AIUIConstant::SYNC_DATA_STATUS:
					break;

				case AIUIConstant::SYNC_DATA_ACCOUNT:
					break;

				case AIUIConstant::SYNC_DATA_SCHEMA:
				{
					string sid = event.getData()->getString("sid", "");
					string tag = event.getData()->getString("tag", "");

					//mSyncSid = sid;

					if (AIUIConstant::SUCCESS == retcode)
					{
						cout << "sync schema success." << endl;
					} else {
						cout << "sync schema error=" << retcode << endl;
					}

					cout << "sid=" << sid << endl;
					cout << "tag=" << tag << endl;
				} break;

				case AIUIConstant::SYNC_DATA_SPEAKABLE:
					break;

				case AIUIConstant::SYNC_DATA_QUERY://查询结果
				{
					if (AIUIConstant::SUCCESS == retcode)
					{
						cout << "sync status success" << endl;
					} else {
						cout << "sync status error=" << retcode << endl;
					}
				} break;
			}
		} else if (AIUIConstant::CMD_QUERY_SYNC_STATUS == event.getArg1()) {
			int syncType = event.getData()->getInt("sync_dtype", -1);
			if (AIUIConstant::SYNC_DATA_QUERY == syncType)
			{
				string result = event.getData()->getString("result", "");
				cout << "result:" << result << endl;

				if (0 == event.getArg2())
				{
					cout << "sync status:success." << endl;
				} else {
					cout << "sync status error:" << event.getArg2() << endl;
				}
			}
		} else if (AIUIConstant::CMD_BUILD_GRAMMAR == event.getArg1()) {
			if (event.getArg2() == 0)
			{
				cout << "build grammar success." << endl;
			}
			else
			{
				cout << "build grammar error, errcode = " << event.getArg2() << endl;
				cout << "error reasion is " << event.getInfo() << endl;
			}
		} else if (AIUIConstant::CMD_UPDATE_LOCAL_LEXICON == event.getArg1()) {
			if (event.getArg2() == 0)
			{
				cout << "update lexicon success" << endl;
			}
			else
			{
				cout << "update lexicon error, errcode = " << event.getArg2() << endl;
				cout << "error reasion is " << event.getInfo() << endl;
			}
		}
	} break;

	case AIUIConstant::EVENT_ERROR:
		{
			cout << "EVENT_ERROR:" << event.getArg1() << endl;
			cout << " ERROR info is " << event.getInfo() << endl;
		} break;
	}
}